<?php

namespace app\shop\model\order;

use app\common\model\order\Order as OrderModel;
use app\common\enum\order\OrderPayStatusEnum;
use app\shop\service\order\ExportService;
use think\facade\Db;

/**
 * 订单模型
 */
class Order extends OrderModel
{
    /**
     * 订单列表
     */
    public function getList($dataType, $data = null)
    {
        $model = $this;
        // 检索查询条件
        $model = $model->setWhere($model, $data);
        // 获取数据列表
        $list = $model->alias('order')
            ->join('user', 'user.user_id=order.user_id')
            ->with(['stallinfo','product' => ['image', 'refund'], 'user', 'supplier', 'advance', 'store', 'clerk', 'system_coupons', 'gift_product_order' => ['gift_product', 'file']])
            ->where('order.is_delete', '=', 0)
            ->where($this->transferDataType($dataType))
            ->field('order.*')
            ->order(['order.create_time' => 'desc'])
            ->paginate($data);
        foreach ($list as &$item) {
            $item["is_first_order"] = Order::getFirstOrderId($item) == $item["order_id"];
        }
        return $list;
    }

    /**
     * 获取订单总数
     */
    public function getCount($type = 'all', $user_id = 0, $referee_id = 0, $shop_supplier_ids = 0)
    {
        // 筛选条件
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case 'delivery';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'cancel';
                $filter['order_status'] = 21;
                break;
            case 'canceled';
                $filter['order_status'] = 20;
                break;
            case 'is_invoice';
                $filter['is_invoice'] = 1;
                break;
            case 'is_invoiced';
                $filter['is_invoice'] = 2;
                break;
            case 'refund';
                //20240510 Mr.Z 添加售后中
                $filter['is_order_refund'] = 1;
                $filter['order_status'] = 20;
                break;
        }
        if ($user_id > 0) {
            $filter["order.user_id"] = $user_id;
        }
        if ($referee_id > 0) {
            $filter["user.referee_id"] = $referee_id;
            $filter[] = ['order.pay_price', ">", 0];
        }
        if ($shop_supplier_ids) {
            //2024/5/17 kevin
            $filter[] = ['order.shop_supplier_id','in',$shop_supplier_ids];
        }
        return $this->withJoin(['user'])->where($filter)->count();
    }

    /**
     * 订单列表(全部)
     */
    public function getListAll($dataType, $query = [])
    {
        $model = $this;
        // 检索查询条件
        $model = $model->setWhere($model, $query);
        // 获取数据列表
         $list = $model->with(['product.image', 'address', 'user', 'extract', 'extract_store', 'advance'])
            ->alias('order')
            ->field('order.*')
            ->join('user', 'user.user_id = order.user_id')
            ->where($this->transferDataType($dataType))
            ->where('order.is_delete', '=', 0)
            ->order(['order.create_time' => 'desc'])
            ->select();
        foreach ($list as &$item) {
            $item["is_first_order"] = Order::getFirstOrderId($item) == $item["order_id"];
        }
        return $list;
    }

    /**
     * 订单导出
     */
    public function exportList($dataType, $query)
    {
        // 获取订单列表
        $list = $this->getListAll($dataType, $query);
        // 导出excel文件
        return (new Exportservice)->orderList($list,true,$this);
    }

    /**
     * 设置检索查询条件
     */
    private function setWhere($model, $data)
    {
        //搜索订单号
        if (isset($data['order_no']) && $data['order_no'] != '') {
            $model = $model->where('order_no', 'like', '%' . trim($data['order_no']) . '%');
        }
        //搜索自提门店
        if (isset($data['store_id']) && $data['store_id'] != '') {
            $model = $model->where('extract_store_id', '=', $data['store_id']);
        }
        //搜索配送方式
        if (isset($data['style_id']) && $data['style_id'] != '') {
            $model = $model->where('delivery_type', '=', $data['style_id']);
        }
        //搜索时间段
        if (isset($data['create_time']) && $data['create_time'] != '') {
            $sta_time = array_shift($data['create_time']);
            $end_time = array_pop($data['create_time']);
            $model = $model->whereBetweenTime('order.create_time', $sta_time, date('Y-m-d 23:59:59', strtotime($end_time)));
        }
        if (!empty($data['user_id'])) {
            $model = $model->where('user.user_id', $data['user_id']);
        } elseif (isset($data['search']) && $data['search']) {
            $model = $model->where('user.user_id|user.nickName|user.mobile', 'like', '%' . $data['search'] . '%');
        }
        if (!empty($data['referee_id'])) {
            $model = $model->where('user.referee_id', $data['referee_id']);
            $model = $model->where('order.pay_price', ">", 0);
        }
        if (!empty($data['shop_supplier_id'])) {
            $model = $model->where('order.shop_supplier_id',$data['shop_supplier_id']);
        }
        if (isset($data['shop_supplier_ids']) && $data['shop_supplier_ids']) {
            $model = $model->where('order.shop_supplier_id', 'in',$data['shop_supplier_ids']);
        }
        return $model;
    }

    /**
     * 转义数据类型条件
     */
    private function transferDataType($dataType)
    {
        $filter = [];
        // 订单数据类型
        switch ($dataType) {
            case 'all':
                break;
            case 'payment';
                $filter['pay_status'] = OrderPayStatusEnum::PENDING;
                $filter['order_status'] = 10;
                break;
            case 'delivery';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'received';
                $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
                $filter['delivery_status'] = 20;
                $filter['receipt_status'] = 10;
                $filter['order_status'] = 10;
                break;
            case 'comment';
//                $filter['is_comment'] = 0; //kevin 2024/5/17 待评价跟已完成订单合并
                $filter['order_status'] = 30;
                break;
            case 'complete';
//                $filter['is_comment'] = 1;//kevin 2024/5/17 待评价跟已完成订单合并
                $filter['order_status'] = 30;
                break;
            case 'cancel';
                $filter['order_status'] = 21;
                break;
            case 'canceled';
                $filter['order_status'] = 20;
                break;
            case 'is_invoice';
                $filter['is_invoice'] = 1;
                break;
            case 'is_invoiced';
                $filter['is_invoice'] = 2;
                break;
            case 'refund';
                //20240510 Mr.Z 添加售后中
                $filter['is_order_refund'] = 1;
                $filter['order_status'] = 20;
                break;
        }
        return $filter;
    }

    /**
     * 获取待处理订单
     */
    public function getReviewOrderTotal()
    {
        $filter['pay_status'] = OrderPayStatusEnum::SUCCESS;
        $filter['delivery_status'] = 10;
        $filter['order_status'] = 10;
        $filter['order_status'] = 10;
        return $this->withJoin(['user']) ->where($filter)->count();
    }

    /**
     * 获取某天的总销售额
     * 结束时间不传则查一天
     */
    public function getOrderTotalPrice($startDate = null, $endDate = null)
    {
        $model = $this;
        if($startDate && !$endDate){
            $model = $model->where('pay_time', '>=', strtotime($startDate));
            $model = $model->where('pay_time', '<', strtotime($startDate) + 86400);
        }elseif($startDate && $endDate){
            $model = $model->where('pay_time', '>=', strtotime($startDate));
            $model = $model->where('pay_time', '<', strtotime($endDate) + 86400);
        }

        $count = $model->where('pay_status', OrderPayStatusEnum::SUCCESS)
            ->where('order_status', '<>', 20)
            ->where('is_delete', '=', 0)
            ->sum('pay_price');

        return $count;
    }

    /**
     * 获取某天的客单价
     * 结束时间不传则查一天
     */
    public function getOrderPerPrice($startDate = null, $endDate = null)
    {
        $model = $this;
        $model = $model->where('pay_time', '>=', strtotime($startDate));
        if (is_null($endDate)) {
            $model = $model->where('pay_time', '<', strtotime($startDate) + 86400);
        } else {
            $model = $model->where('pay_time', '<', strtotime($endDate) + 86400);
        }
        return $model->where('pay_status', '=', 20)
            ->where('order_status', '<>', 20)
            ->where('is_delete', '=', 0)
            ->avg('pay_price');
    }

    /**
     * 获取某天的下单用户数
     */
    public function getPayOrderUserTotal($day)
    {
        $startTime = strtotime($day);
        $userIds = $this->distinct(true)
            ->where('pay_time', '>=', $startTime)
            ->where('pay_time', '<', $startTime + 86400)
            ->where('pay_status', '=', 20)
            ->where('is_delete', '=', 0)
            ->column('user_id');
        return count($userIds);
    }

    /**
     * 获取兑换记录
     * @param $param array
     * @return \think\Paginator
     */
    public function getExchange($param)
    {
        $model = $this;
        if (isset($param['order_status']) && $param['order_status'] > -1) {
            $model = $model->where('order.order_status', '=', $param['order_status']);
        }
        if (isset($param['nickName']) && !empty($param['nickName'])) {
            $model = $model->where('user.nickName', 'like', '%' . trim($param['nickName']) . '%');
        }

        return $model->with(['user'])->alias('order')
            ->join('user', 'user.user_id = order.user_id')
            ->where('order.order_source', '=', 20)
            ->where('order.is_delete', '=', 0)
            ->order(['order.create_time' => 'desc'])
            ->paginate($param);
    }

    /**
     * 获取平台的总销售额
     */
    public function getTotalMoney($type = 'all', $is_settled = -1)
    {
        $model = $this;
        $model = $model->where('pay_status', '=', 20)
            ->where('order_status', '<>', 20)
            ->where('is_delete', '=', 0);
        if ($is_settled == 0) {
            $model = $model->where('is_settled', '=', 0);
        }
        if ($type == 'all') {
            return $model->sum('pay_price');
        } else if ($type == 'supplier') {
            return $model->sum('supplier_money');
        } else if ($type == 'sys') {
            return $model->sum('sys_money');
        }
        return 0;
    }

    /**
     * 获取视频订单
     */
    public function getAgentLiveOrder($params)
    {
        $model = $this;
        if (isset($params['order_no']) && !empty($params['order_no'])) {
            $model = $model->where('order.order_no', 'like', '%' . trim($params['order_no']) . '%');
        }
        if (isset($params['room_name']) && !empty($params['room_name'])) {
            $model = $model->where('room.name', 'like', '%' . trim($params['room_name']) . '%');
        }
        if (isset($params['nickName']) && !empty($params['nickName'])) {
            $model = $model->where('user.nickName', 'like', '%' . trim($params['real_name']) . '%');
        }
        if (isset($params['supplier_name']) && !empty($params['supplier_name'])) {
            $model = $model->where('supplier.name', 'like', '%' . trim($params['supplier_name']) . '%');
        }
        return $model->alias('order')->field(['order.*'])->with(['product.image', 'user', 'room.user', 'supplier'])
            ->join('live_room room', 'room.room_id = order.room_id', 'left')
            ->join('supplier supplier', 'supplier.shop_supplier_id = room.shop_supplier_id', 'left')
            ->join('user user', 'user.user_id = room.user_id', 'left')
            ->where('order.room_id', '>', 0)
            ->where('order.is_delete', '=', 0)
            ->order(['order.create_time' => 'desc'])
            ->paginate($params);
    }

    public static function getFirstOrderId($data)
    {
        return (new static())->where("user_id", $data["user_id"])
            ->where("order_source", "<>", 80)
            ->where("pay_status", "=", "20")
            ->where("order_status", "<>", "20")
            ->order("pay_time")
            ->value("order_id");
    }

    public function export($dataType, $query)
    {
        $list = $this->getList($dataType, $query);
        $fields = [
            ["title" => '订单号', 'field' => 'order_no'],
            ["title" => '商品信息', 'field' => 'product_name', "product_list" => true],
            ["title" => '商品规格', 'field' => 'product_attr', "product_list" => true],
            ["title" => '商品单价', 'field' => 'product_price', "product_list" => true],
            ["title" => '购买数量', 'field' => 'total_num', "product_list" => true],
            ["title" => '商品总价', 'field' => 'total_price', "product_list" => true],
            ["title" => '订单总额', 'field' => 'total_price'],
            ["title" => '优惠券抵扣', 'field' => 'coupon_money'],
            ["title" => '实付款金额', 'value' => function ($order) {
                return $order['order_source'] == 70 ? round($order['pay_price'] + $order['advance']['pay_price'], 2) : $order['pay_price'];
            }],
            ["title" => '支付方式', 'value' => '微信'],
            ["title" => '下单时间', 'field' => 'create_time'],
            ["title" => '买家', 'field' => 'user.nickName'],
            ["title" => '买家ID', 'field' => 'user.user_id'],
            ["title" => '买家留言', 'field' => 'buyer_remark'],
            ["title" => '收货人姓名', 'field' => 'address.name'],
            ["title" => '收货人电话', 'field' => 'address.phone'],
            ["title" => '骑手姓名', 'field' => 'store_clerk.name'],
            ["title" => '骑手电话', 'field' => 'store_clerk.phone'],
            ["title" => '收货人地址', 'value' => function ($order) {
                return $order['address'] ? $order['address']->getFullAddress() : '';
            }],
            ["title" => '付款状态', 'field' => 'pay_status.text'],
            ["title" => '付款时间', 'field' => "pay_time", "format" => "datetime"],
            ["title" => '发货时间', 'field' => "delivery_time", "format" => "datetime"],
            ["title" => '收货状态', 'field' => 'receipt_status.text'],
            ["title" => '收货时间', 'field' => 'receipt_time', "format" => "datetime"],
            ["title" => '订单状态', 'field' => 'order_status.text'],
            ["title" => '是否已评价', 'field' => 'is_comment', "format" => "enum", 'list' => [1 => "是", 0 => "否"]],
            ["title" => '门店', 'field' => 'store.store_name'],
        ];

        $sheetname = "订单明细";
        $filename = '订单-' . date('YmdHis') . '.xlsx';
        $aoa = [];
        $titles = [];
        foreach ($fields as $index => $field) {
            $titles[] = $field["title"];
        }
        $aoa[] = $titles;
        $merges = [];
        $startLine = 0;
        foreach ($list as $item) {
            $inside_line = 0;
            $startLine++;
            $endLine = $startLine - 1;
            $item['store_clerk'] = $this->getStoreClerk($item);

            foreach ($item['product'] as $product) {
                $row = [];
                foreach ($fields as $field) {
                    if ($inside_line > 0 && !isset($field["product_list"])) {
                        $row[] = "";
                        continue;
                    }
                    if (isset($field["value"])) {
                        $row[] = is_callable($field["value"]) ? $field["value"]($item) : $field["value"];
                        continue;
                    }
                    if (isset($field["product_list"])) {
                        $value = $product[$field["field"]] ?? "";
                    } else {
                        $fieldPaths = explode(".", $field["field"]);
                        $value = count($fieldPaths) == 2 ? ($item[$fieldPaths[0]][$fieldPaths[1]] ?? "") : ($item[$field["field"]] ?? "");
                    }
                    if (isset($field["format"])) {
                        $value = $this->getFormatValue($field, $value);
                    }
                    $row[] = $value;
                }
                $inside_line++;
                $aoa[] = $row;
                $endLine++;
            }
            if ($endLine > $startLine) {
                foreach ($fields as $index => $field) {
                    if (!isset($field["product_list"])) {
                        $merges[] = ['s' => ['c' => $index, 'r' => $startLine], 'e' => ['c' => $index, 'r' => $endLine]];
                    }
                }
            }
        }
        return compact("aoa", 'merges', "sheetname", "filename");

    }

    protected function getFormatValue($field, $value)
    {
        switch ($field["format"]) {
            case "datetime":
                return $value ? date("Y-m-d H:i:s", (int)$value) : "";
            case "enum":
                return $field["list"][$value] ?? $value;
        }
        return $value;
    }

    /**
     * @param $item
     * @return []
     */
    public function getStoreClerk($item)
    {
        $data = ["name" => "", "phone" => ""];
        if (empty($item["store_clerk_id"])) {
            return $data;
        }

        if ($item["is_store_clerk_id"] == 1) {
            $clerk = Db::name("store_clerk")->find($item["store_clerk_id"]);
            if (empty($clerk)) return $data;
            return ["name" => $clerk["real_name"], "phone" => $clerk["mobile"]];
        }
        $shopper = Db::name("shopper")->find($item["store_clerk_id"]);
        if (empty($shopper)) return $data;
        return ["name" => $shopper["username"], "phone" => $shopper["mobile"]];

    }
}
